﻿using System;
using System.Collections.Generic;
using System.Drawing.Design;
using System.Linq;
using System.Windows.Forms.Design;
using devtm.Editor.TypeSelector;
using DslModeling = global::Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling;
using System.Windows.Forms;
using System.Reflection;


namespace devtm.AutoMapper
{
    public class ListeMemberEditor2 : UITypeEditor
    {

        protected DslModeling.Store Store;
        protected MapperShape Instance;

        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
        {

            IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if (edSvc != null)
            {

                bool isSource = context.PropertyDescriptor.Name.Contains("Source");

                Instance = context.Instance as MapperShape;
                Store = Instance.Store;
                Mapper mapper = GetMapper(context);
                TypeElement typeElement = GetTypeElement(context, mapper);

                TreeView control = new TreeView();

                TreeNode t = new TreeNode() { Text = "Instance", Tag = "Instance", ToolTipText = "Instance" };

                GetNodeMembers(typeElement.Type, t);
                control.Nodes.Add(t);
                t.Expand();

                if (isSource)
                    BuildSubProperties(t);

                int indx = 0;
                if (!string.IsNullOrEmpty(value as string))
                {
                    string[] tb = (value as string).Split('.');
                    FindProperty(tb, control, t, ref indx);
                }

                if (isSource)
                    control.BeforeExpand +=
                        (sender, e) =>
                        {
                            BuildSubProperties(e.Node);
                        };

                control.AfterSelect +=
                (sender, e) =>
                {

                    try
                    {

                        if (value as string == control.SelectedNode.ToolTipText)
                            return;

                        value = control.SelectedNode.ToolTipText;

                    }
                    catch (Exception)
                    {

                    }

                    if (sender != null)
                        if ((sender as TreeView).SelectedNode != null)
                            edSvc.CloseDropDown();

                };

                edSvc.DropDownControl(control);

            }

            return value;

        }

        private void BuildSubProperties(TreeNode t)
        {
            foreach (TreeNode t2 in t.Nodes)
            {

                if (t2.Nodes.Count > 0)
                    continue;

                Type type = null;
                PropertyInfo p1 = t2.Tag as PropertyInfo;

                if (p1 != null)
                    type = p1.PropertyType;
                else
                    type = (t2.Tag as FieldInfo).FieldType;

                if (type.IsEnum)
                    continue;

                string n = type.FullName;

                if (!NewMapperHelper.types.Contains(n))
                    GetNodeMembers(type, t2);

            }
        }

        private void BuildSubProperty(TreeNode t)
        {

                if (t.Nodes.Count > 0)
                    return;

                Type type = null;
                PropertyInfo p1 = t.Tag as PropertyInfo;

                if (p1 != null)
                    type = p1.PropertyType;
                else
                    type = (t.Tag as FieldInfo).FieldType;

                if (type.IsEnum)
                    return;

                string n = type.FullName;

                if (!NewMapperHelper.types.Contains(n))
                    GetNodeMembers(type, t);

        }

        private void FindProperty(string[] value, TreeView control, TreeNode t, ref int index)
        {

            foreach (TreeNode item in t.Nodes)
            {
         
                if (item.Text == value[index])
                {
                    control.SelectedNode = item;

                    if (index < value.Length - 1)
                    {
                        index++;

                        if (item.Nodes.Count == 0)
                            BuildSubProperty(item);


                        FindProperty(value, control, item, ref index);
                        
                    }
                    return;

                }
            }
        }


        private void GetNodeMembers(Type type, TreeNode t)
        {

            foreach (MemberInfo item in type.GetMembers())

                if (item is PropertyInfo || item is FieldInfo)
                {
                    TreeNode t2 = new TreeNode()
                    {
                        Tag = item,
                        Text = item.Name,
                        ToolTipText = GetName(t, item)
                    };
                    t.Nodes.Add(t2);
                }

        }

        private static string GetName(TreeNode t, MemberInfo item)
        {
            if (t.ToolTipText == "Instance")
                return item.Name;

            return t.Tag != null && !string.IsNullOrEmpty(t.ToolTipText) ? t.ToolTipText + "." + item.Name : item.Name;

        }


        private static Mapper GetMapper(System.ComponentModel.ITypeDescriptorContext context)
        {
            MapperShape p1 = context.Instance as MapperShape;

            Mapper mapper = p1.ModelElement as Mapper;

            return mapper;
        }


        public override bool IsDropDownResizable
        {
            get
            {
                return true;
            }
        }


        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {

            if (context != null)
            {

                Instance = context.Instance as MapperShape;
                Store = Instance.Store;
                Mapper mapper = GetMapper(context);                
                TypeElement typeElement = GetTypeElement(context, mapper);

                Type type = mapper.MappingModel.FindType(typeElement.AssemblyQualifiedName);

                if (typeElement.Type != null)
                    return UITypeEditorEditStyle.DropDown;

            }

            return UITypeEditorEditStyle.None;
        }

        private static TypeElement GetTypeElement(System.ComponentModel.ITypeDescriptorContext context, Mapper mapper)
        {
            if (context.PropertyDescriptor.Name.Contains("Source"))
                return mapper.MappingSource.TypeElement;

            return mapper.MappingDestination.TypeElement;

        }


    }
}
